/**
 * 版权所有(C)，上海海鼎信息工程股份有限公司，2009，所有权利保留。
 * 
 * 项目名：	rumba-widget2
 * 文件名：	RCheckBox.java
 * 模块说明：	
 * 修改历史：
 * Feb 4, 2009 - lxm - 创建。
 */
package com.hd123.rumba.gwt.widget2.client.form;

import com.google.gwt.event.dom.client.BlurEvent;
import com.google.gwt.event.dom.client.BlurHandler;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.event.dom.client.FocusEvent;
import com.google.gwt.event.dom.client.FocusHandler;
import com.google.gwt.event.dom.client.HasAllFocusHandlers;
import com.google.gwt.event.dom.client.HasAllKeyHandlers;
import com.google.gwt.event.dom.client.HasClickHandlers;
import com.google.gwt.event.dom.client.KeyDownEvent;
import com.google.gwt.event.dom.client.KeyDownHandler;
import com.google.gwt.event.dom.client.KeyPressEvent;
import com.google.gwt.event.dom.client.KeyPressHandler;
import com.google.gwt.event.dom.client.KeyUpEvent;
import com.google.gwt.event.dom.client.KeyUpHandler;
import com.google.gwt.event.shared.HandlerRegistration;
import com.google.gwt.user.client.DOM;
import com.google.gwt.user.client.Event;
import com.google.gwt.user.client.ui.ClickListener;
import com.google.gwt.user.client.ui.FlowPanel;
import com.google.gwt.user.client.ui.FocusListener;
import com.google.gwt.user.client.ui.Focusable;
import com.google.gwt.user.client.ui.HTML;
import com.google.gwt.user.client.ui.HasFocus;
import com.google.gwt.user.client.ui.KeyboardListener;
import com.google.gwt.user.client.ui.ListenerWrapper;
import com.google.gwt.user.client.ui.SourcesClickEvents;
import com.google.gwt.user.client.ui.Widget;
import com.hd123.rumba.gwt.widget2.client.fielddef.FieldDef;
import com.hd123.rumba.gwt.widget2.client.fielddef.HasFieldDef;
import com.hd123.rumba.gwt.widget2.client.panel.FlowPanelHelper;

/**
 * 标准控件CheckBox。
 * <p>
 * 
 * <b>控件结构</b><br>
 * FlowPanel<br>
 * ..RSimpleCheckBox<br>
 * ..[RCaption{HTML} class=caption]<br>
 * ..[HTML class=note]<br>
 * <p>
 * 
 * <b>CSS Style Rules</b> <ol type=disc>
 * <li>.rb-CheckBox {}</li>
 * <li>.rb-CheckBox-disabled {}</li>
 * <li>.rb-CheckBox .rb-SimpleCheckBox {}</li>
 * <li>.rb-CheckBox .caption {}</li>
 * <li>.rb-CheckBox .note {}</li> </ol>
 * 
 * @author lxm
 * 
 */
@SuppressWarnings("deprecation")
public class RCheckBox extends RFieldComposite implements HasFocus, Focusable, HasAllFocusHandlers,
    HasAllKeyHandlers, SourcesClickEvents, HasClickHandlers, HasFieldDef {

  private static final String STYLENAME_DEFAULT = "rb-CheckBox";

  /**
   * 创建对象结构。
   */
  public RCheckBox() {
    super();
    drawSelf();
  }

  /**
   * @param fieldDef
   *          字段定义
   */
  public RCheckBox(FieldDef fieldDef) {
    this();
    setFieldDef(fieldDef);
  }

  private FlowPanel pnl;
  private Helper_pnl pnlHelper;
  private RSimpleCheckBox checkBox;
  private FieldDef fieldDef;

  private static final String CNAME_CHECKBOX = "checkBox";
  private static final String CNAME_CAPTION = "caption";
  private static final String CNAME_NOTE = "note";

  /** 标题 */
  public String getCaption() {
    return getFieldCaption();
  }

  /** 标题 */
  public void setCaption(String caption) {
    setFieldCaption(caption);
  }

  public void setFieldCaption(String fieldCaption) {
    super.setFieldCaption(fieldCaption);

    if (!includedByLabeledBox()) {
      RCaption ctrl = (RCaption) pnlHelper.getChild(CNAME_CAPTION);
      ctrl.setHTML(fieldCaption);
    }
  }

  /** 注释信息。 */
  public String getNote() {
    if (!pnlHelper.isCreated(CNAME_NOTE))
      return null;
    HTML html = (HTML) pnlHelper.getChild(CNAME_NOTE);
    return html.getHTML();
  }

  /** 注释信息。 */
  public void setNote(String note) {
    HTML html = (HTML) pnlHelper.getChild(CNAME_NOTE);
    html.setHTML(note);
  }

  public void setEnabled(boolean enabled) {
    super.setEnabled(enabled);
    checkBox.setEnabled(enabled);
    if (!pnlHelper.isCreated(CNAME_CAPTION))
      return;
    RCaption w = (RCaption) pnlHelper.getChild(CNAME_CAPTION);
    if (enabled)
      DOM.removeElementAttribute(w.getElement(), "disabled");
    else
      DOM.setElementAttribute(w.getElement(), "disabled", "true");
  }

  /** 是否被选中。默认为false。 */
  public boolean isChecked() {
    return checkBox.isChecked();
  }

  /** 是否被选中。默认为false。 */
  public void setChecked(boolean checked) {
    checkBox.setChecked(checked);
  }

  /**
   * 设置选中状态。
   * 
   * @param checked
   *          指定是否被选中。
   * @param fireClick
   *          指定是否同时触发onClick事件。
   */
  public void setChecked(boolean checked, boolean fireClick) {
    checkBox.setChecked(checked, fireClick);
  }

  /** 是否只读。默认为false。 */
  public boolean isReadOnly() {
    return checkBox.isReadOnly();
  }

  /** 是否只读。默认为false。 */
  public void setReadOnly(boolean readOnly) {
    checkBox.setReadOnly(readOnly);
  }

  public boolean isRequired() {
    return false;
  }

  public void setFieldCaptionListener(RFieldCaptionListener listener) {
    super.setFieldCaptionListener(listener);
    // 当被放入RLabeledBox，则不显示caption部分
    if (pnlHelper.isCreated(CNAME_CAPTION)) {
      RCaption w = (RCaption) pnlHelper.getChild(CNAME_CAPTION);
      if (includedByLabeledBox())
        w.setHTML("");
      else
        w.setHTML(getCaption());
    }
  }

  public int getTabIndex() {
    return checkBox.getTabIndex();
  }

  public void setTabIndex(int index) {
    checkBox.setTabIndex(index);
  }

  public void setAccessKey(char key) {
    checkBox.setAccessKey(key);
  }

  public void setFocus(boolean focused) {
    checkBox.setFocus(focused);
  }

  /**
   * @deprecated 请用{@link #addFocusHandler}和
   *             {@link #addBlurHandler}代替
   */
  @Deprecated
  public void addFocusListener(FocusListener listener) {
    ListenerWrapper.WrappedFocusListener.add(this, listener);
  }

  /**
   * @deprecated 请用{@link #addFocusHandler}和
   *             {@link #addBlurHandler}返回的
   *             {@link HandlerRegistration#removeHandler}代替
   */
  @Deprecated
  public void removeFocusListener(FocusListener listener) {
    ListenerWrapper.WrappedFocusListener.remove(this, listener);
  }

  public HandlerRegistration addFocusHandler(FocusHandler handler) {
    return addDomHandler(handler, FocusEvent.getType());
  }

  public HandlerRegistration addBlurHandler(BlurHandler handler) {
    return addDomHandler(handler, BlurEvent.getType());
  }

  /**
   * @deprecated 请用{@link #addKeyUpHandler}、
   *             {@link #addKeyDownHandler}和
   *             {@link #addKeyPressHandler} 代替
   */
  @Deprecated
  public void addKeyboardListener(KeyboardListener listener) {
    ListenerWrapper.WrappedKeyboardListener.add(this, listener);
  }

  /**
   * @deprecated 请用{@link #addKeyUpHandler}、
   *             {@link #addKeyDownHandler}和
   *             {@link #addKeyPressHandler}返回的
   *             {@link HandlerRegistration#removeHandler}代替
   */
  @Deprecated
  public void removeKeyboardListener(KeyboardListener listener) {
    ListenerWrapper.WrappedKeyboardListener.remove(this, listener);
  }

  public HandlerRegistration addKeyDownHandler(KeyDownHandler handler) {
    return addDomHandler(handler, KeyDownEvent.getType());
  }

  public HandlerRegistration addKeyUpHandler(KeyUpHandler handler) {
    return addDomHandler(handler, KeyUpEvent.getType());
  }

  public HandlerRegistration addKeyPressHandler(KeyPressHandler handler) {
    return addDomHandler(handler, KeyPressEvent.getType());
  }

  /**
   * @deprecated 请用{@link #addClickHandler}代替
   */
  @Deprecated
  public void addClickListener(ClickListener listener) {
    ListenerWrapper.WrappedClickListener.add(this, listener);
  }

  /**
   * @deprecated 请用{@link #addClickHandler}返回的
   *             {@link HandlerRegistration#removeHandler}代替
   */
  @Deprecated
  public void removeClickListener(ClickListener listener) {
    ListenerWrapper.WrappedClickListener.remove(this, listener);
  }

  public HandlerRegistration addClickHandler(ClickHandler handler) {
    return addDomHandler(handler, ClickEvent.getType());
  }

  public FieldDef getFieldDef() {
    return fieldDef;
  }

  public void setFieldDef(FieldDef fieldDef) {
    this.fieldDef = fieldDef == null ? null : fieldDef.clone();
    if (this.fieldDef == null)
      return;

    setFieldCaption(this.fieldDef.getCaption());
    setRequired(this.fieldDef.isRequired());
  }

  public void onBrowserEvent(Event event) {
    switch (DOM.eventGetType(event)) {
    case Event.ONCLICK:
      if (!isEnabled() || isReadOnly()) {
        event.preventDefault();
        return;
      }
      break;
    }

    super.onBrowserEvent(event);
  }

  private void drawSelf() {
    pnl = new FlowPanel();
    pnlHelper = new Helper_pnl();

    pnlHelper.appendChild(CNAME_CHECKBOX, false);
    pnlHelper.appendChild(CNAME_CAPTION, true);
    pnlHelper.appendChild(CNAME_NOTE, true);

    initWidget(pnl);
    setStyleName(STYLENAME_DEFAULT);
  }

  private class Helper_pnl extends FlowPanelHelper {
    public Helper_pnl() {
      super(pnl);
    }

    protected Widget createChild(String childName) {
      if (CNAME_CHECKBOX.equals(childName)) {
        checkBox = new RSimpleCheckBox();
        SimpleCheckBoxHandler simpleCheckBoxHandler = new SimpleCheckBoxHandler();
        checkBox.addClickHandler(simpleCheckBoxHandler);
        checkBox.addFocusHandler(simpleCheckBoxHandler);
        checkBox.addBlurHandler(simpleCheckBoxHandler);

        return checkBox;
      }

      if (CNAME_CAPTION.equals(childName)) {
        return new RCaption();
      }

      if (CNAME_NOTE.equals(childName)) {
        HTML html = new HTML();
        html.setStyleName("note");
        return html;
      }
      return null;
    }
  }

  private class RCaption extends HTML {

    public RCaption() {
      super();
      setStyleName("caption");
      sinkEvents(Event.ONCLICK);
    }

    public void onBrowserEvent(Event event) {
      super.onBrowserEvent(event);
      if (Event.ONCLICK == DOM.eventGetType(event)) {
        if (checkBox.isEnabled())
          checkBox.setFocus(true);
        // checkBox.setChecked(!checkBox.isChecked(), true);
      }
    }
  }

  /**
   * 内部复选框的事件处理
   * 
   * @author LiQi
   * 
   */
  private class SimpleCheckBoxHandler implements ClickHandler, FocusHandler, BlurHandler {

    public void onClick(ClickEvent event) {
      if (isEnabled() && !isReadOnly())
        RCheckBox.this.fireEvent(event);
      event.stopPropagation();
    }

    public void onFocus(FocusEvent event) {
      RCheckBox.this.fireEvent(event);
    }

    public void onBlur(BlurEvent event) {
      RCheckBox.this.fireEvent(event);
    }
  }
}
